#include <iostream>
#include <array>
#include <tuple>
#include <string>
#include <sstream>

using namespace std;

namespace TraitsLearn2 {


    /*
    问题描述

    首先来看 traits 技术可以解决什么问题，
    我们拥有自定义类型Foo, Bar，以及编译器自带类型 int, double, string，
    我们想要为这些不同的类型提供统一的编码函数 decode() ，该怎样实现呢？
    方案一
    定义五个函数
    // 内置类型 int, double
    void decode(const int data, char* buf);
    void decode(const unsigned int data, char* buf);
    void decode(const double data, char* buf);
    // 自定义类型 Foo, Bar
    void decode(const Foo& data, char* buf);
    void decode(const Bar& data, char* buf);

    方案二：模板函数+内置字段， 系统自定义变量 int, double 而言，是无法在其内部定义 type 的，所以，变成定义4个函数
    // 自定义类型
    enum Type {
      TYPE_1,
      TYPE_2
    };
    class Foo {
      Type type = Type::TYPE_1;
    };
    class Bar {
    public:
      Type type = Type::TYPE_2;
    };
    // 模板函数
    template<typename T>
    void decode(const T& data, char* buf) {
      if(T::type == Type::TYPE_1) {
        ...
      }
      else if(T::type == Type::TYPE_2) {
        ..
      }


    方案三：traits 模板类， 只有一个函数
    // 定义数据 type 类
    enum Type {
      TYPE_1,
      TYPE_2,
      TYPE_3
    }
    // 自定义数据类型
    class Foo {
    public:
      Type type = TYPE_1;
    };
    class Bar {
    public:
      Type type = TYPE_2;
    };
    template<typename T>
    struct type_traits {
      Type type = T::type;
    }

    // 统一的编码函数
    template<typename T>
    void decode(const T& data, char* buf) {
      if(type_traits<T>::type == Type::TYPE_1) {
        ...
      }
      else if(type_traits<T>::type == Type::TYPE_2) {
        ...
      }
    }
    使用第三个模板类 traits，利用模板特化的功能，实现对自定义数据和编译器内置数据的统一
    tratis 技术常见于标准库的实现中，但对日常开发中降低代码冗余也有很好的借鉴意义
    */
    enum Type {
        TYPE_1,
        TYPE_2,
        TYPE_3
    };
    // 自定义数据类型
    class Foo {
   
    };
    class Bar {
   
    };
    template<typename T>//其它TYPE_3 
    struct type_traits {
        static  const Type type = TYPE_3;
    };
    //Foo TYPE_1
    template<>
    struct type_traits<Foo> {
        static  const Type type = Type::TYPE_1;
    };
    template<>//Bar TYPE_2
    struct type_traits<Bar> {
        static  const Type type = TYPE_2;
    };
 

    // 统一的编码函数
    template<typename T>
    void decode(const T& data, char* buf) {
        if (type_traits<T>::type == Type::TYPE_1) {
        //  //  ...
        }
        //else if (type_traits<T>::type == Type::TYPE_2) {
        //  //  ...
        //}
        stringstream out;
        
       out << "type=" << type_traits<T>::type << std::endl;
        cout<<(out.str());
        out.str("");
    }
    int main()
    {
        char buf[10];
        Bar bar;
        decode(bar, buf);
        Foo foo;
        decode(foo, buf);

        stringstream out;
        out << "\n\n以下都是 type3 :\n";
        cout<<(out.str());
        out.str("");
        int v1 = 10;
        decode(&v1,buf);
        decode(v1, buf);
        float v2 = 10;
        decode(&v2, buf);
        decode(v2, buf);

        return 0;
    }
}
